﻿using System.Linq.Expressions;

using Tszy.Unlimited.Base.Exceptions;
using Tszy.Unlimited.Data.AdoNet.Sql.Components.Expressions.Values;
using Tszy.Unlimited.Data.AdoNet.Sql.Descriptors;

namespace Tszy.Unlimited.Data.AdoNet.Sql.Components.Expressions.Where.Comparison
{
    internal abstract class WhereComparisonExpressionHandlerBase : WhereExpressionHandlerBase
    {
        public override WhereExpressionResult Execute(ExpressionContext context, Expression expression)
        {
            var binaryExpression = expression as BinaryExpression;

            var comparisonExpressionDescriptor = Execute(context, binaryExpression?.Left, binaryExpression?.Right);

            return new WhereExpressionResult { Status = true, ComparisonExpressionDescriptor = comparisonExpressionDescriptor };
        }

        /// <summary>
        /// 解析最简表达式并转换成 SQL 脚本。
        /// </summary>
        /// <param name="context"></param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        private IWhereComparisonExpressionDescriptor Execute(ExpressionContext context, Expression left, Expression right)
        {
            var leftResult = ValueExpressionHandler.Handler(context, left);
            var rightResult = ValueExpressionHandler.Handler(context, right);

            if (!leftResult.Status || !rightResult.Status)
            {
                throw new MainApplicationException("WhereComparisonExpressionHandler 表达式中获取参数错误");
            }

            var comparisonExpressionDescriptor = new WhereComparisonExpressionDescriptor
            {
                Left = new WhereComparisonExpressionParameter
                {
                    ParmeterType = GetParameterType(leftResult.Type),
                    PropertyType = leftResult.PropertyType,
                    ParmeterValue = GetParmeterValue(leftResult),
                },
                Right = new WhereComparisonExpressionParameter
                {
                    ParmeterType = GetParameterType(rightResult.Type),
                    PropertyType = rightResult.PropertyType,
                    ParmeterValue = GetParmeterValue(rightResult),
                },
                ComparisonDescriptor = GetComparison(),
            };

            return comparisonExpressionDescriptor;
        }

        private static WhereComparisonExpressionParameterType GetParameterType(ValueExpressionType expressionType)
        {
            var parameterType = WhereComparisonExpressionParameterType.Parameter;

            if (expressionType == ValueExpressionType.Value)
            {
                parameterType = WhereComparisonExpressionParameterType.Value;
            }

            return parameterType;
        }

        private static object GetParmeterValue(ValueExpressionResult value)
        {
            if (value.Type == ValueExpressionType.Parameter)
            {
                return $"{value?.Value ?? string.Empty}";
            }

            return value.Value;
        }

        protected virtual string GetComparison()
        {
            return string.Empty;
        }
    }
}